package com.elitel.frame.business.filter.serverparam;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.elitel.common.CustomHttpServletRequestWrapper;
import com.elitel.frame.main.entity.vo.JsonResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Map;

import static com.elitel.common.core.constant.RequestConstant.APP_CODE;
import static com.elitel.common.core.constant.RequestConstant.TOKEN;

public class ParamTranslateFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(ParamTranslateFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    /**
     * @param req   The request to process
     * @param resp  The response associated with the request
     * @param chain Provides access to the next filter in the chain for this
     *              filter to pass the request and response to for further
     *              processing
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        String method = request.getMethod();
        String header = request.getHeader("Content-Type");

        // 如果是post请求，且请求头包含application/json 
        if (RequestMethod.POST.toString().equalsIgnoreCase(method) && header != null && header.contains(MediaType.APPLICATION_JSON)) {
            try {
                // 处理请求体内容
                String bodyContent = request.getReader().lines().reduce("", (accumulator, actual) -> accumulator + actual);
                if (StringUtils.isNotBlank(bodyContent)) {

                    // 将请求体内容转换为参数 这里不适合深度解析 只是解析json的最外层
                    JSONObject map = JSONObject.parseObject(bodyContent);
                    if (!ObjectUtils.isEmpty(map)) {
                        CustomHttpServletRequestWrapper cust = new CustomHttpServletRequestWrapper(request);
                        Map<String, String[]> parameterMap = cust.getParameterMap();
                        map.forEach((k, v) -> {
                            // 字符串类型
                            if (v instanceof String) {
                                parameterMap.put(k, new String[]{(String) v});
                                cust.setParameter(k, (String) v);
                            }
                            // json对象类型
                            if (v instanceof JSONObject) {
                                String jsonVal = JSONObject.toJSONString(v);
                                parameterMap.put(k, new String[]{jsonVal});
                                cust.setParameter(k, jsonVal);
                            }
                            // json数组类型
                            if (v instanceof JSONArray && !ObjectUtils.isEmpty(v)) {
                                JSONArray jsonArray = (JSONArray) v;
                                String[] strings = new String[jsonArray.size()];
                                for (int i = 0; i < jsonArray.size(); i++) {
                                    Object item = jsonArray.get(i);
                                    if (item instanceof String) {
                                        strings[i] = (String) item;
                                    }
                                    if (item instanceof JSONObject) {
                                        strings[i] = JSONObject.toJSONString(v);
                                    }
                                    if (basicType(item)) {
                                        strings[i] = String.valueOf(item);
                                    }
                                }
                                parameterMap.put(k, strings);
                                cust.setParameter(k, JSONObject.toJSONString(v));
                            }

                        });
                        // 将请求头中的TOKEN放在requestParam的appCode中
                        String token = request.getHeader(TOKEN);
                        if (StringUtils.isNotBlank(token)) {
                            cust.setParameter(APP_CODE, token);
                        }

                        // 替换request
                        request = cust;
                    }
                }
            } catch (Exception e) {
                logger.error("请求参数转换异常", e);
                write(response, "访问受限，请检查输入参数的格式。");
                return;
            }


        }

        if (RequestMethod.GET.toString().equalsIgnoreCase(method)) {
            // 将请求头中的TOKEN放在requestParam的appCode中
            String token = request.getHeader(TOKEN);
            if (StringUtils.isNotBlank(token)) {
                CustomHttpServletRequestWrapper cust = new CustomHttpServletRequestWrapper(request);
                cust.setParameter(APP_CODE, token);
                request = cust;
            }
        }
        chain.doFilter(request, response);
    }


    /**
     * 判断数据是不是基本数据类型
     *
     * @param data
     * @return
     */
    private Boolean basicType(Object data) {
        Class[] basicType = new Class[]{Integer.class, Long.class, Double.class, Float.class, Boolean.class};
        return Arrays.asList(basicType).contains(data.getClass());
    }


    public void write(HttpServletResponse response, String msg) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        JsonResult jr = new JsonResult();
        jr.setMsg(msg);
        jr.setSuccess(false);
        out.write(JSON.toJSONString(jr));
        out.flush();
        out.close();
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
